package ffte.core.flat

import spinal.core._
import spinal.lib._

import ffte.types.VecComplex
import ffte.property.{getFFTIW,getFFTOW,FFTIOConfig}
import ffte.algorithm.FFTGen.{Method,combineFT}
import ffte.core.{fft,combine}
/**
 * Flat FFT I/O interface bundle
 *
 * Defines the standard interface for flat (non-pipelined) FFT implementations.
 * This bundle provides the input and output connections required for
 * single-cycle FFT computation with proper clock control.
 *
 * Interface Characteristics:
 * - Input: N complex samples with input precision dW
 * - Output: N complex samples with output precision oW
 * - Control: Clock enable signal for timing control
 * - Timing: Single-cycle computation with registered output
 *
 * Master/Slave Configuration:
 * The bundle implements the IMasterSlave interface, allowing it to be used
 * as either master or slave depending on the connection direction. This provides
 * flexibility for connecting FFT components in different configurations.
 *
 * @param N Number of complex samples per FFT
 * @param dW Input data width in bits
 * @param oW Output data width in bits
 */
case class flatIO(N: Int, dW: Int, oW: Int) extends Bundle with IMasterSlave {
    /**
     * Input data port
     *
     * N complex input samples with specified precision.
     * Input data is captured when the FFT computation is enabled.
     */
    val d = VecComplex(N, dW)

    /**
     * Output data port
     *
     * N complex output samples with specified precision.
     * Results become valid after one clock cycle of computation.
     */
    val q = VecComplex(N, oW)

    /**
     * Clock enable signal
     *
     * Controls when the FFT computation should be performed.
     * When asserted, the component processes the input data and
     * produces output on the next clock cycle.
     */
    val ce = in(Bool)

    /**
     * Master interface configuration
     *
     * Configures the bundle as a master interface where:
     * - Output (q) is driven by this component
     * Input (d) is driven by external source
     * This is the standard configuration for FFT components.
     */
    def asMaster = {
        out(q)
        in(d)
    }
}

/**
 * Base trait for flat FFT components
 *
 * Provides common functionality for all flat (non-pipelined) FFT implementations.
 * This trait serves as the foundation for components that complete FFT computation
 * in a single clock cycle using combinatorial logic.
 *
 * Flat Architecture Characteristics:
 * - Single-cycle computation (combinatorial logic)
 * - No internal pipelining registers
 * - High resource usage but minimal latency
 * - Suitable for latency-critical applications
 * - Deterministic timing behavior
 *
 * Inheritance Hierarchy:
 * - Extends Component: SpinalHDL component base class
 * - Extends fft: Common FFT interface with timing
 * - Provides I/O generation utilities
 *
 * @tparam N Transform size (number of points)
 * @tparam dW Input data width in bits
 * @tparam oW Output data width in bits
 */
trait flatComponents extends Component with fft {
    /** Transform size - number of points in the FFT */
    def N: Int

    /** Standard I/O interface for flat FFT components */
    val io: flatIO

    /**
     * Generate master I/O interface
     *
     * Creates a master interface configuration for the flatIO bundle.
     * This is the standard configuration for FFT components where
     * they drive the output and receive input from external sources.
     *
     * @return Master-configured flatIO bundle
     */
    def iogen = master(flatIO(N, dW, oW))
}

/**
 * Combined flat FFT components trait
 *
 * Extends flat components to support multi-stage FFT implementations
 * that combine two smaller FFT operations. This trait provides the infrastructure
 * for hierarchical FFT decomposition in flat architecture.
 *
 * Multi-Stage Architecture:
 * - Two-stage decomposition: First stage and second stage
 * - Independent scaling for each stage to optimize precision
 * - Hierarchical structure for large FFT decompositions
 * - Single-cycle computation through combinatorial logic cascade
 *
 * Scaling Strategy:
 * - First stage (fg): Uses first_shift bits for overflow prevention
 * - Second stage (sg): Uses second_shift bits for overflow prevention
 * - Scaling distribution optimized for computational accuracy
 * - Prevents overflow in intermediate results
 *
 * @tparam T Implementation method type (Flat, Mixed, Streamed)
 */
trait combineFlatComponents[T <: Method] extends flatComponents with combine[T] {
    /**
     * First stage FFT processor
     *
     * Implements the inner FFT computation using first_shift scaling.
     * Processes groups of input data and produces intermediate results.
     */
    val fg = new Flat(first_shift)

    /**
     * Second stage FFT processor
     *
     * Implements the outer FFT computation using second_shift scaling.
     * Combines results from the first stage to produce final output.
     */
    val sg = new Flat(second_shift)
}
